package com.atguigu.gulimall.product;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

/**
    告诉mybatis-plus,sql映射文件的位置
 自动创建变量引用快捷键：ctrl+alt+v；


 2、逻辑删除
    1）、配置全局的逻辑删除规则(省略)
    2）、配置逻辑删除的组件Bean(省略)
    3）、（Bean）实体类字段上加上@TableLogic注解
 3.JSR303
    1)给Bean添加校验注解 :javax.validation.constraints 并定义自己的 message提示
    2)开启校验功能 BrandController中有实例 如：public R save(@Valid @RequestBody BrandEntity brand)，不满足会有默认的响应
    3)给校验的bean后紧跟一个BindingResult，就可能获取到校验的结果
    public R save(@Valid @RequestBody BrandEntity brand, BindingResult result)
    4)分组校验 （多场景的复杂校验） 例如:BrandEntity
        1)、@NotNull(message = "修改必须指定品牌id",groups = {UpdateGroup.class})
          给校验注解标注什么情况需要进行校验
        2)、@Validated(AddGroup.class)
        3、没有指定分组的校验注解@NotBlank,在分组校验情况下@Validated(AddGroup.class)不生效，只会在@Validated下生效
    5）自定义校验
        1)、编写一个自定义的校验注解
        2）、编写一个自定义的校验器ConstraintValidator
        3）、关联自定义的校验器和自定义的校验注解
             @Documented
             @Constraint(validatedBy = { ListValueConstraintValidator.class //【可以指定多个不同的校验器适配不同类型的校验】})
             @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
             @Retention(RUNTIME)
 4.统一的异常处理
   1、编写异常类处理类，使用@ControllerAdvice
   2、使用@ExceptionHandler标注方法可能处理的异常

 5、模板引擎
   1）、thymeleaf-starter :关闭缓存
   2）、静态资源都放在static文件夹下就可以直接访问
   3）、页面放在templates文件夹下
        springboot，访问项目时，默认会找index
   4）、页面修改不重启服务器实时更新
      1）、引入dev-tools
      2)、修改完页面 Ctrl + Shift + F9重新自动编译页面，代码及配置，需重启服

 6、整合Redsi
      1)、引入data-redis-starter
      2)、简单配置redis的host等信息
      3）、使用SpringBoot 自动配置StringRedisTemplate来操作redis
 7、整合redisson作为所有分布式锁，分布式对象等功能框架
     1）、引入依赖
             <dependency>
             <groupId>org.redisson</groupId>
             <artifactId>redisson</artifactId>
             <version>3.12.0</version>
             </dependency>
     2）、配置redisson
              MyRedissonConfig给容器中配置一个RedissonClient实例即可
     3)、参照文档做
 8、整合SpringCache简化缓存开发
     1)、引入依赖
             spring-boot-starter-cache   spring-boot-starter-data-redis
     2）、写配置
         1）、自动配置了哪些 CacheAutoConfiguration 会导入 RedisCacheConfiguration
             自动配好了缓存管理器RedisCacheManager
         2）、配置使用redis作为缓存
         3）、测试使用缓存
             @Cacheable: Triggers cache population.  触发将数据保存到缓存的操作
             @CacheEvict: Triggers cache eviction.   触发将数据从缓存删除的操作
             @CachePut: Updates the cache without interfering with the method execution. 不影响方法执行更新缓存
             @Caching: Regroups multiple cache operations to be applied on a method.  组合以上多个操作
             @CacheConfig: Shares some common cache-related settings at class-level.  在类级别共缓存的相同配置
             （1）配置开启缓存功能   @EnableCaching
             （2）只需要使用注解就能完成缓存操作
         4) spring-cache的不足
             1）读模式
            缓存穿透：查询一个null数据。解决：缓存空数据
            缓存击穿：大量并发进来，同时查询一个正好过期的数据 解决：加锁 ？默认无加锁 sync = true(加锁)
            缓存雪崩：大量的key同时过期，解决：加随机时间，加上过期时间  spring.cache.redis.time-to-live=3600000

            2）写模式: (缓存与数据库一致)
              1）、读写加锁（读多写少）
              2）、引入Canal:感知到Mysql的更新去更新redis
              3)、读多写多：直接去数据库查询
            总结：常规数据（读多少，即时性，一致性不高的数据）完全可以使用springCache；写模式（只要缓存的数据有过期时间就足够了）
             特殊数据：特殊设计
            原理： CacheManager(RedisCacheManager)->Cache(RedisCache)->Cache负责缓存的读写
 */
@EnableRedisHttpSession
@EnableCaching
@EnableFeignClients(basePackages = "com.atguigu.gulimall.product.feign")
@EnableDiscoveryClient
@MapperScan("com.atguigu.gulimall.product.dao")
@SpringBootApplication
public class GulimallProductApplication {

    public static void main(String[] args) {

        SpringApplication.run(GulimallProductApplication.class, args);
    }

}
